﻿using System;
using System.Reflection;
using Shell.Build;

namespace Shell.Ioc
{
    public class IocBuildPlan : IBuildPlan, IDisposable
    {
        public IocBuildPlan(ConstructorInfo constructor)
        {
            this.Constructor = constructor;
            this.parameterInfos = this.Constructor.GetParameters();
            this.Parameters = new object[this.parameterInfos.Length];
        }

        protected ParameterInfo[] parameterInfos { get; private set; }

        public IBuildContext Context { get; private set; }

        public ConstructorInfo Constructor { get; private set; }

        public object[] Parameters { get; private set; }

        public bool IsExecutable
        {
            get
            {
                foreach (var p in this.Parameters)
                {
                    if (p == null)
                    {
                        return false;
                    }
                }
                return true;
            }
        }

        public void Initialize(IBuildContext context)
        {
            this.Context = context;
        }

        public void Execute()
        {
            if (!this.IsExecutable)
            {
                this.ResolveParameters();
            }
            if (this.IsExecutable)
            {
                this.Context.Output = this.Constructor.Invoke(this.Parameters);
                this.Context.IsCompleted = this.Context.Output != null;
            }
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void ResolveParameters()
        {
            for (int i = 0; i < this.Parameters.Length; i++)
            {
                this.Parameters[i] = this.Context.Shell.Resolve(null, this.parameterInfos[i].ParameterType);
            }
        }

        protected virtual void Dispose(bool disposing)
        {
            this.Context = null;
        }
    }
}
